package com.zzzy.doc.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuozhengsoft.pageoffice.word.DataRegionReader;
import com.zzzy.common.util.AssertUtil;
import com.zzzy.common.util.CglibBeanCopierUtil;
import com.zzzy.common.util.FileUtil;
import com.zzzy.common.vo.PageResult;
import com.zzzy.doc.common.util.InitDataPageOfficeUtil;
import com.zzzy.doc.dao.entity.DocFileTemplate;
import com.zzzy.doc.dao.mapper.DocFileTemplateMapper;
import com.zzzy.doc.dto.DataRegionDto;
import com.zzzy.doc.vo.template.*;
import com.zzzy.doc.vo.template.file.DocFileTemplatePageRes;
import com.zzzy.framework.common.constant.CommonMenuOperateConstant;
import com.zzzy.framework.common.enums.common.TemplateStatusEnum;
import com.zzzy.framework.common.util.SecurityUtils;
import com.zzzy.framework.core.mybatis.query.LambdaQueryWrapperE;
import com.zzzy.framework.dto.LoginUser;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 公文文件模板
 *
 * @author fc
 * @since 2024-08-08
 */
@Service
public class DocFileTemplateService extends ServiceImpl<DocFileTemplateMapper, DocFileTemplate> {

    public PageResult<DocFileTemplate> getPage(DocTemplatePageReq queryReq) {
        LambdaQueryWrapperE<DocFileTemplate> queryWrapperE = new LambdaQueryWrapperE<>();
        queryWrapperE.select(DocFileTemplate::getId, DocFileTemplate::getName, DocFileTemplate::getStatus
                , DocFileTemplate::getUserId, DocFileTemplate::getUserName, DocFileTemplate::getUpdateTime, DocFileTemplate::getCreateTime);

        queryWrapperE.likeIfPresent(DocFileTemplate::getName, queryReq.getName())
                .likeIfPresent(DocFileTemplate::getUserName, queryReq.getUserName())
                .eqIfPresent(DocFileTemplate::getStatus, queryReq.getStatus())
                .orderByDesc(DocFileTemplate::getId);
        return baseMapper.selectPage(queryReq, queryWrapperE);
    }

    public Long add(DocTemplateAddReq addReq) {
        DocFileTemplate fileTemplate = CglibBeanCopierUtil.copy(addReq, DocFileTemplate.class);
        //初始化word
        byte[] approvalFileByte = FileUtil.getFileByteFromClassPath("office/template/approvalTemplate.docx");
        fileTemplate.setApprovalFileBlob(approvalFileByte);
        fileTemplate.setApprovalFileExtName("." + FileUtil.DOCX);
        fileTemplate.setApprovalInitDataRegions(InitDataPageOfficeUtil.getInitDataRegionList());
        fileTemplate.setApprovalDataRegions(fileTemplate.getApprovalInitDataRegions());
        byte[] mainTemplateByte = FileUtil.getFileByteFromClassPath("office/template/mainTemplate.docx");
        fileTemplate.setMainFileBlob(mainTemplateByte);
        fileTemplate.setMainFileExtName("." + FileUtil.DOCX);
        fileTemplate.setMainInitDataTags(InitDataPageOfficeUtil.getInitDataTagList());
        fileTemplate.setStatus(TemplateStatusEnum.CREATE.getValue());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        fileTemplate.setUserId(loginUser.getId());
        fileTemplate.setUserName(loginUser.getNickName());
        fileTemplate.setCreateTime(LocalDateTime.now());
        baseMapper.insert(fileTemplate);
        return fileTemplate.getId();
    }

    public DocFileTemplate getByIdForQuery(Long id) {
        DocFileTemplate docFileTemplate = baseMapper.selectById(id);
        AssertUtil.nonNull(docFileTemplate, "公文模板不存在");
        return docFileTemplate;
    }

    public void updateBasicInfoById(DocTemplateSimpleUpdateReq updateReq) {
        DocFileTemplate docFileTemplate = getByIdForUpdate(updateReq.getId());
        AssertUtil.isEquals(TemplateStatusEnum.CREATE.getValue(), docFileTemplate.getStatus(), "只有新建状态的模板可修改");
        CglibBeanCopierUtil.copy(updateReq, docFileTemplate);
        docFileTemplate.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(docFileTemplate);
    }

    private DocFileTemplate getByIdForUpdate(Long id) {
        DocFileTemplate docFileTemplate = getByIdForQuery(id);
        Long loginUserId = SecurityUtils.getLoginUser().getId();
        AssertUtil.isEquals(docFileTemplate.getUserId(), loginUserId, "当前用户无修改此模板权限");
        return docFileTemplate;
    }

    public void deleteById(Long id) {
        DocFileTemplate docFileTemplate = getByIdForUpdate(id);
        AssertUtil.isEquals(TemplateStatusEnum.CREATE.getValue(), docFileTemplate.getStatus(), "只有新建状态的模板可删除");
        baseMapper.deleteById(id);
    }

    public void updateTemplateApprovalWord(Long id, byte[] byteArray, String fileExtName) {
        AssertUtil.isTrue(fileExtName.toLowerCase().endsWith(FileUtil.DOCX), "请上传docx格式的word文件");
        AssertUtil.isTrue(FileUtil.checkIsWord(byteArray), "上传的文件非word格式");
        AssertUtil.isTrue(!FileUtil.isChangeFileExtendType(fileExtName, byteArray), "上传的文件手动修改过文件扩展名,请另存文件后重试");
        DocFileTemplate docFileTemplate = getByIdForUpdate(id);
        AssertUtil.isEquals(TemplateStatusEnum.CREATE.getValue(), docFileTemplate.getStatus(), "只有新建状态的模板可修改");
        docFileTemplate.setApprovalFileBlob(byteArray);
        docFileTemplate.setApprovalFileExtName(fileExtName);

        docFileTemplate.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(docFileTemplate);
    }

    public void updateTemplateApprovalDataRegion(Long id, List<DataRegionReader> dataRegionReaderList) {
        DocFileTemplate docFileTemplate = getByIdForUpdate(id);
        Map<String, DataRegionDto> regionDtoMap = docFileTemplate.getApprovalDataRegions().stream()
                .collect(Collectors.toMap(DataRegionDto::getName, dataRegionDto -> dataRegionDto));
        List<DataRegionDto> newDataRegionList = dataRegionReaderList.stream()
                .map(dataRegionReader -> {
                    DataRegionDto dataRegionDto = new DataRegionDto(dataRegionReader.getName(), dataRegionReader.getValue(), "");
                    if (regionDtoMap.containsKey(dataRegionDto.getName())) {
                        CglibBeanCopierUtil.copy(regionDtoMap.get(dataRegionDto.getName()), dataRegionDto);
                    }
                    return dataRegionDto;
                }).collect(Collectors.toList());
        docFileTemplate.setApprovalDataRegions(newDataRegionList);
        baseMapper.updateById(docFileTemplate);
    }

    public void updateTemplateMainWord(Long id, byte[] byteArray, String fileExtName) {
        AssertUtil.isTrue(fileExtName.toLowerCase().endsWith(FileUtil.DOCX), "请上传docx格式的word文件");
        AssertUtil.isTrue(FileUtil.checkIsWord(byteArray), "上传的文件非word格式");
        AssertUtil.isTrue(!FileUtil.isChangeFileExtendType(fileExtName, byteArray), "上传的文件手动修改过文件扩展名,请另存文件后重试");
        DocFileTemplate docFileTemplate = getByIdForUpdate(id);
        AssertUtil.isEquals(TemplateStatusEnum.CREATE.getValue(), docFileTemplate.getStatus(), "只有新建状态的模板可修改");
        docFileTemplate.setMainFileBlob(byteArray);
        docFileTemplate.setMainFileExtName(fileExtName);
        docFileTemplate.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(docFileTemplate);
    }

    /**
     * 克隆模板
     */
    public Long cloneById(Long id) {
        DocFileTemplate existsDocFileTemplate = getByIdForQuery(id);
        DocFileTemplate fileTemplate = CglibBeanCopierUtil.copy(existsDocFileTemplate, DocFileTemplate.class);
        fileTemplate.setId(null);
        fileTemplate.setName(existsDocFileTemplate.getName()+"【NEW】");
        fileTemplate.setStatus(TemplateStatusEnum.CREATE.getValue());
        fileTemplate.setCreateTime(LocalDateTime.now());
        baseMapper.insert(fileTemplate);
        return fileTemplate.getId();
    }

    public void enable(Long id) {
        DocFileTemplate docFileTemplate = getByIdForUpdate(id);
        AssertUtil.isEquals(TemplateStatusEnum.CREATE.getValue(), docFileTemplate.getStatus(), "模板状态错误");
        docFileTemplate.setStatus(TemplateStatusEnum.ENABLE.getValue());
        docFileTemplate.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(docFileTemplate);
    }

    public void disable(Long id) {
        DocFileTemplate docFileTemplate = getByIdForUpdate(id);
        AssertUtil.isEquals(TemplateStatusEnum.ENABLE.getValue(), docFileTemplate.getStatus(), "模板状态错误");
        docFileTemplate.setStatus(TemplateStatusEnum.DISABLED.getValue());
        docFileTemplate.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(docFileTemplate);
    }

    public PageResult<DocFileTemplatePageRes> getDocFileTemplateResPage(DocTemplatePageReq queryReq) {
        PageResult<DocFileTemplate> docFileTemplatePage = getPage(queryReq);
        //组装返回数据,判断数据按钮权限
        List<DocFileTemplatePageRes> templatePageResList = docFileTemplatePage.getList().stream().map(docFileTemplate -> {
            DocFileTemplatePageRes.Button button = getButton(docFileTemplate.getId());
            DocFileTemplatePageRes docFileTemplatePageRes = new DocFileTemplatePageRes();
            docFileTemplatePageRes.setData(docFileTemplate);
            docFileTemplatePageRes.setButton(button);
            return docFileTemplatePageRes;
        }).collect(Collectors.toList());

        PageResult pageResult = CglibBeanCopierUtil.copy(docFileTemplatePage, PageResult.class);
        pageResult.setList(templatePageResList);
        return pageResult;
    }

    public DocFileTemplatePageRes.Button getButton(Long docFileTemplateId) {
        DocFileTemplate template = getByIdForQuery(docFileTemplateId);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getId();
        boolean hasUpdate = loginUser.hasControllerPermission(CommonMenuOperateConstant.UPDATE);
        DocFileTemplatePageRes.Button button = new DocFileTemplatePageRes.Button();
        boolean isCurrentUser = userId.equals(template.getUserId());
        boolean update = TemplateStatusEnum.CREATE.getValue().equals(template.getStatus())
                && hasUpdate && isCurrentUser;
        button.setUpdate(update);
        button.setDelete(update);
        button.setEnable(update);
        boolean disable = TemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())
                && hasUpdate && isCurrentUser;
        button.setDisable(disable);
        return button;
    }

    public PageResult<DocFileTemplate> getDocFileTemplatePageForSelect(DocTemplateForSelectPageReq queryReq) {
        LambdaQueryWrapperE<DocFileTemplate> queryWrapperE = new LambdaQueryWrapperE<>();
        queryWrapperE.select(DocFileTemplate::getId, DocFileTemplate::getName, DocFileTemplate::getStatus
                , DocFileTemplate::getUserId, DocFileTemplate::getUserName, DocFileTemplate::getUpdateTime, DocFileTemplate::getCreateTime);

        queryWrapperE.likeIfPresent(DocFileTemplate::getName, queryReq.getName())
                .eqIfPresent(DocFileTemplate::getStatus, TemplateStatusEnum.ENABLE.getValue())
                .orderByDesc(DocFileTemplate::getId);
        return baseMapper.selectPage(queryReq, queryWrapperE);
    }
}
